package com.huanzhidadi.okhttp.util;

import com.huanzhidadi.okhttp.constant.CommonConstant;
import okhttp3.*;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

public class OkHttpUtils {

    private OkHttpUtils() {
        throw new IllegalStateException("Utility class");
    }

    private static OkHttpClient.Builder okHttpClientBuilder = null;

    /**
     * 空闲连接数
     */
    private static final int MAX_IDLE_CONNECTIONS = 30000;
    /**
     * 保持连接时间
     */
    private static final long KEEP_ALIVE_TIME = 120000L;
    /**
     * 连接超时时间
     */
    private static final int CONNECTION_TIME_OUT = 120000;
    /**
     * 读写超时时间
     */
    private static final int SOCKET_TIME_OUT = 120000;

    private static OkHttpClient.Builder getHttpClientBuilder() {
        if (null == okHttpClientBuilder) {
            synchronized(OkHttpUtils.class) {
                if (null == okHttpClientBuilder) {
                    ConnectionPool connectionPool = new ConnectionPool(MAX_IDLE_CONNECTIONS, KEEP_ALIVE_TIME, TimeUnit.MILLISECONDS);
                    Dispatcher dispatcher = new Dispatcher();
                    dispatcher.setMaxRequests(60000);
                    dispatcher.setMaxRequestsPerHost(60000);
                    okHttpClientBuilder = new OkHttpClient.Builder()
                            .connectionPool(connectionPool)
                            .readTimeout(SOCKET_TIME_OUT, TimeUnit.MILLISECONDS)
                            .writeTimeout(SOCKET_TIME_OUT, TimeUnit.MILLISECONDS)
                            .connectTimeout(CONNECTION_TIME_OUT, TimeUnit.MILLISECONDS)
                            .dispatcher(dispatcher)
                            .followRedirects(false)
                            // 自动重连设置为false
                            .retryOnConnectionFailure(false);
                }
            }
        }
        return okHttpClientBuilder;
    }

    private static OkHttpClient.Builder getHttpsClientBuilder(){
        ConnectionPool connectionPool = new ConnectionPool(MAX_IDLE_CONNECTIONS, KEEP_ALIVE_TIME, TimeUnit.MILLISECONDS);
        return new OkHttpClient.Builder()
                .connectionPool(connectionPool)
                .readTimeout(SOCKET_TIME_OUT, TimeUnit.MILLISECONDS)
                .writeTimeout(SOCKET_TIME_OUT, TimeUnit.MILLISECONDS)
                .connectTimeout(CONNECTION_TIME_OUT, TimeUnit.MILLISECONDS)
                // 自动重连设置为false
                .retryOnConnectionFailure(false);

    }

    public static Response postWithHeader(String url, String body, String charset, Map<String, String> headers)
            throws IOException{
        charset = Optional.ofNullable(charset).orElse(CommonConstant.CODE_FORMAT);
        OkHttpClient okHttpClient;
        if(url.contains(CommonConstant.HTTPS)){
            okHttpClient = getHttpsClientBuilder().build();
        } else {
            okHttpClient = getHttpClientBuilder().build();
        }
        MediaType mediaType = MediaType.get("application/json;charset=" + charset);
        RequestBody requestBody = RequestBody.create(mediaType, body);
        Request.Builder reqBuilder = new Request.Builder().url(url).post(requestBody);
        // 自定义设置header
        headers.forEach(reqBuilder::addHeader);
        Request request = reqBuilder.build();
        return okHttpClient.newCall(request).execute();
    }


    public static Response getWithHeader(String url, Map<String, String> headers)
            throws IOException{
        OkHttpClient okHttpClient;
        if(url.contains(CommonConstant.HTTPS)){
            okHttpClient = getHttpsClientBuilder().build();
        } else {
            okHttpClient = getHttpClientBuilder().build();
        }
        Request.Builder reqBuilder = new Request.Builder().url(url).get();
        // 自定义设置header
        headers.forEach(reqBuilder::addHeader);
        Request request = reqBuilder.build();
        return okHttpClient.newCall(request).execute();
    }

    public static Response post(String url, String body, String charset)
            throws IOException{
        charset = Optional.ofNullable(charset).orElse(CommonConstant.CODE_FORMAT);
        OkHttpClient okHttpClient;
        if(url.contains(CommonConstant.HTTPS)){
            okHttpClient = getHttpsClientBuilder().build();
        } else {
            okHttpClient = getHttpClientBuilder().build();
        }
        MediaType mediaType = MediaType.get("application/json;charset=" + charset);
        RequestBody requestBody = RequestBody.create(mediaType, body);
        Request.Builder reqBuilder = new Request.Builder().url(url).post(requestBody);
        Request request = reqBuilder.build();
        return okHttpClient.newCall(request).execute();
    }

    /**
     * 发送异步POST请求
     *
     * @param url      请求地址
     * @param body     body参数，json格式
     * @param charset  编码
     * @param callback 回调方法
     */
    public static void post(String url, String body, String charset, Callback callback) {
        charset = Optional.ofNullable(charset).orElse(CommonConstant.CODE_FORMAT);
        OkHttpClient okHttpClient;
        if(url.contains(CommonConstant.HTTPS)){
            okHttpClient = getHttpsClientBuilder().build();
        } else {
            okHttpClient = getHttpClientBuilder().build();
        }
        Map<String, String> headers = new HashMap<>();
        headers.put("Accept", "application/json");
        headers.put("Content-Type", "application/json");
        //headers.put("Connection", "close");

        MediaType mediaType = MediaType.get("application/json;charset=" + charset);
        RequestBody requestBody = RequestBody.create(mediaType, body);
        Request.Builder reqBuilder = new Request.Builder().url(url).post(requestBody);
        // 自定义设置header
        headers.forEach(reqBuilder::addHeader);
        Request request = reqBuilder.build();
        okHttpClient.newCall(request).enqueue(callback);
    }
}
